package com.zsc.wxapp.utils;

import com.zsc.wxapp.properties.MinIOProperty;
import io.minio.BucketExistsArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Slf4j
@Component
public class MinIOUtil {

    @Resource
    private MinIOProperty minIOProperty;
    @Resource
    private MinioClient minioClient;

//    @Bean
    public String uploadFile(MultipartFile file) {
        // 获取桶名
        String bucketName = minIOProperty.getBucketName();
        log.info("开始向桶 {} 上传文件", bucketName);
        log.info("minio地址是：{}", minIOProperty.getEndpoint());
        //给文件生成一个唯一名称  当日日期-uuid.后缀名
        String folderName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"));
        String fileName = String.valueOf(UUID.randomUUID());
        String extName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));//文件后缀名
        String objectName = folderName + "-" + fileName + extName;

        InputStream inputStream;
        try {
            inputStream = file.getInputStream();
            // 配置参数
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName)
                    .stream(inputStream, file.getSize(), -1).contentType(file.getContentType()).build();
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
            inputStream.close();
        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException |
                 InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException |
                 XmlParserException e) {
            log.error("文件上传失败: " + e);
            return null;
        }
        log.info("文件上传成功，文件名为：{}", objectName);
//        return objectName;

        // 文件url
        String fileUrl;
        try {
            if (StringUtils.isBlank(objectName)) {
                log.error("获取文件预览url失败，文件名为空！");
                return null;
            }
            // 判断桶是否存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            // 桶存在
            if (isExist) {
                fileUrl = minioClient.getPresignedObjectUrl(
                        GetPresignedObjectUrlArgs.builder()
                                .method(Method.PUT)
                                .bucket(bucketName)
                                .object(objectName)
                                .expiry(2, TimeUnit.HOURS) // 限时两个小时之后过期
                                .build());

                Integer index = fileUrl.indexOf("?");
                String result = null;
                if (index != -1) {
                    result = fileUrl.substring(0, index);
                    log.info("文件url: {}", result);
                }
                return result;
            } else {  // 桶不存在
                log.error("获取文件预览url失败，桶{}不存在", bucketName);
                throw new RuntimeException("桶不存在");
            }
        } catch (Exception e) {
            log.error("获取文件预览url时出现异常: " + e.getMessage());
            throw new RuntimeException(e);
        }
    }

}
